import express from "express";
import type { Request, Response, NextFunction } from "express";
import multer from "multer";
import mysql from "mysql2/promise";
import fs from "fs";
import path from "path";
import cors from "cors";
import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";

// 扩展 Express Request 类型
declare global {
  namespace Express {
    interface Request {
      user?: {
        id: number;
        username: string;
        email: string;
      };
    }
  }
}

// 读取配置文件
const config = JSON.parse(fs.readFileSync("mysql_config.json", "utf8"));

// JWT密钥
const JWT_SECRET = "your-jwt-secret-key"; // 在生产环境中应该使用环境变量

// 创建数据库连接池
const pool = mysql.createPool({
  connectionLimit: 10,
  host: config.host,
  user: config.user,
  port: config.port,
  password: config.password,
  database: config.database,
});

// 创建 Express 应用
const app = express();
const port = 3000;

// 使用 cors 中间件处理跨域请求
app.use(cors());
app.use(express.json());

// 登录接口
app.post("/auth/login", async (req: Request, res: Response): Promise<void> => {
  const { username, password } = req.body;

  if (!username || !password) {
    res.status(400).json({ message: "请提供账号和密码" });
    return;
  }

  try {
    // 查找用户
    const [users] = await pool.execute<any[]>(
      "SELECT * FROM users WHERE username = ?",
      [username]
    );

    if (users.length === 0) {
      res.status(401).json({ message: "账号或密码错误" });
      return;
    }

    const user = users[0];

    // 验证密码
    const validPassword = await bcrypt.compare(password, user.password);
    if (!validPassword) {
      res.status(401).json({ message: "账号或密码错误" });
      return;
    }

    res.json({
      message: "登录成功",
      user: {
        id: user.id,
        username: user.username,
      },
    });
  } catch (error) {
    console.error("登录失败:", error);
    res.status(500).json({ message: "登录失败" });
  }
});

// 注册接口
app.post(
  "/auth/register",
  async (req: Request, res: Response): Promise<void> => {
    const { username, password } = req.body;

    if (!username || !password) {
      res.status(400).json({ message: "请提供账号和密码" });
      return;
    }

    try {
      // 检查用户名是否已存在
      const [existingUsers] = await pool.execute<any[]>(
        "SELECT * FROM users WHERE username = ?",
        [username]
      );

      if (existingUsers.length > 0) {
        res.status(400).json({ message: "该账号已被使用" });
        return;
      }

      // 加密密码
      const hashedPassword = await bcrypt.hash(password, 10);

      // 创建新用户
      const [result] = await pool.execute<any>(
        "INSERT INTO users (username, password) VALUES (?, ?)",
        [username, hashedPassword]
      );

      const insertId = (result as any).insertId;

      res.status(201).json({
        message: "注册成功",
        user: {
          id: insertId,
          username,
        },
      });
    } catch (error) {
      console.error("注册失败:", error);
      res.status(500).json({ message: "注册失败" });
    }
  }
);

// 获取当前用户信息
app.get("/api/auth/me", async (req: Request, res: Response): Promise<void> => {
  try {
    const [users] = await pool.execute<any[]>(
      "SELECT id, username, email, created_at FROM users WHERE id = ?",
      [req.user?.id]
    );

    if (users.length === 0) {
      res.status(404).json({ message: "用户不存在" });
      return;
    }

    res.json(users[0]);
  } catch (error) {
    console.error("获取用户信息失败:", error);
    res.status(500).json({ message: "获取用户信息失败" });
  }
});

// 获取当前文件的目录路径
const __dirname = path.resolve();

// 配置静态文件服务 - 使用绝对路径
const imagesDir = path.join(__dirname, "images");
console.log("静态资源目录:", imagesDir); // 打印静态资源目录路径

// 确保图片目录存在
if (!fs.existsSync(imagesDir)) {
  fs.mkdirSync(imagesDir, { recursive: true });
}

// 配置静态文件服务
app.use(
  "/images",
  express.static(imagesDir, {
    setHeaders: (res, path) => {
      res.set("Cross-Origin-Resource-Policy", "cross-origin");
    },
  })
);

// 配置 multer 处理文件上传
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const baseUploadDir = imagesDir;
    const today = new Date();
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, "0");
    const day = String(today.getDate()).padStart(2, "0");

    // 构建年份文件夹路径
    const yearDir = path.join(baseUploadDir, `${year}`);
    // 构建月份文件夹路径
    const monthDir = path.join(yearDir, `${month}`);
    // 构建日期文件夹路径
    const dayDir = path.join(monthDir, `${day}`);

    // 确保年份文件夹存在
    if (!fs.existsSync(yearDir)) {
      fs.mkdirSync(yearDir);
    }
    // 确保月份文件夹存在
    if (!fs.existsSync(monthDir)) {
      fs.mkdirSync(monthDir);
    }
    // 确保日期文件夹存在
    if (!fs.existsSync(dayDir)) {
      fs.mkdirSync(dayDir);
    }

    cb(null, dayDir);
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
    const ext = path.extname(file.originalname);
    cb(null, file.fieldname + "-" + uniqueSuffix + ext);
  },
});

const upload = multer({ storage: storage });

// 处理文件上传的路由
app.post(
  "/upload",
  upload.single("file"),
  async (req: Request, res: Response) => {
    if (!req.file) {
      return res.status(400).json({ message: "未提供文件" });
    }

    let tags = req.body.tags;
    try {
      tags = JSON.parse(tags);
    } catch (parseError) {
      console.error("解析 tags 字段出错:", parseError);
      return res.status(400).json({ message: "tags 字段解析失败" });
    }

    // 将绝对路径转换为相对路径，并移除开头的 images/ 前缀
    const relativePath = path.relative(imagesDir, req.file.path);
    const normalizedPath = relativePath
      .replace(/^images[\/\\]/, "")
      .replace(/\\/g, "/");

    try {
      const query =
        "INSERT INTO images (user_id, file_name, file_size, file_path, tags) VALUES (?, ?, ?, ?, ?)";
      const values = [
        1,
        req.file.filename,
        req.file.size,
        normalizedPath,
        JSON.stringify(tags),
      ];

      const [result] = await pool.execute(query, values);
      res.status(200).json({
        message: "图片上传成功",
        id: result.insertId,
        url: `/images/${normalizedPath}`, // 返回可访问的URL
      });
    } catch (error) {
      console.error("数据库插入错误:", error);
      res.status(500).json({ message: "数据库插入错误" });
    }
  }
);

// 获取图片列表
app.get("/images", async (req: Request, res: Response) => {
  const userId = req.query.userId;

  if (!userId) {
    return res.status(400).json({ message: "缺少用户 ID 参数" });
  }

  try {
    const query = "SELECT * FROM images WHERE user_id = ?";
    const [rows] = await pool.execute(query, [userId]);

    const images = rows.map((row: any) => {
      // 确保文件路径使用正斜杠，并移除重复的 images/ 前缀
      const filePath = row.file_path
        .replace(/^images[\/\\]/, "")
        .replace(/\\/g, "/");
      return {
        id: row.id,
        url: `/images/${filePath}`,
        date: new Date().toISOString().split("T")[0],
        tags: JSON.parse(row.tags),
      };
    });

    res.status(200).json(images);
  } catch (error) {
    console.error("获取图片数据出错:", error);
    res.status(500).json({ message: "获取图片数据失败" });
  }
});

// 根据标签搜索图片
app.get("/images/search", async (req: Request, res: Response) => {
  const userId = req.query.userId;
  const tag = req.query.tag;

  if (!userId) {
    return res.status(400).json({ message: "缺少用户 ID 参数" });
  }

  try {
    let query = "SELECT * FROM images WHERE user_id = ?";
    const queryParams: any[] = [userId];

    if (tag) {
      query += " AND JSON_CONTAINS(tags, ?)";
      queryParams.push(JSON.stringify(tag));
    }

    const [rows] = await pool.execute(query, queryParams);

    const images = rows.map((row: any) => {
      // 确保文件路径使用正斜杠，并移除重复的 images/ 前缀
      const filePath = row.file_path
        .replace(/^images[\/\\]/, "")
        .replace(/\\/g, "/");
      return {
        id: row.id,
        url: `/images/${filePath}`,
        date: new Date().toISOString().split("T")[0],
        tags: JSON.parse(row.tags),
      };
    });

    res.status(200).json(images);
  } catch (error) {
    console.error("搜索图片出错:", error);
    res.status(500).json({ message: "搜索图片失败" });
  }
});

// 获取特定图片详情
app.get("/images/:id", async (req: Request, res: Response) => {
  const imageId = req.params.id;

  if (!imageId) {
    return res.status(400).json({ message: "缺少图片 ID 参数" });
  }

  try {
    const query = "SELECT * FROM images WHERE id = ?";
    const [rows] = await pool.execute(query, [imageId]);

    if (!rows || rows.length === 0) {
      return res.status(404).json({ message: "未找到指定图片" });
    }

    const image = rows[0];
    res.status(200).json({
      id: image.id,
      fileName: image.file_name,
      fileSize: image.file_size,
      filePath: image.file_path,
      tags: JSON.parse(image.tags),
      userId: image.user_id,
    });
  } catch (error) {
    console.error("获取图片详情出错:", error);
    res.status(500).json({ message: "获取图片详情失败" });
  }
});

// 删除图片的路由 (使用GET请求)
app.get("/images/delete/:id", async (req: Request, res: Response) => {
  const imageId = req.params.id;

  if (!imageId) {
    return res.status(400).json({ message: "缺少图片 ID 参数" });
  }

  try {
    // 先获取图片信息，以便删除文件
    const queryGet = "SELECT * FROM images WHERE id = ?";
    const [rows] = await pool.execute(queryGet, [imageId]);

    if (!rows || rows.length === 0) {
      return res.status(404).json({ message: "未找到指定图片" });
    }

    const image = rows[0];
    const filePath = image.file_path;

    // 删除数据库记录
    const queryDelete = "DELETE FROM images WHERE id = ?";
    await pool.execute(queryDelete, [imageId]);

    // 删除文件系统中的文件
    if (fs.existsSync(filePath)) {
      fs.unlinkSync(filePath);
    }

    res.status(200).json({ message: "图片删除成功", id: imageId });
  } catch (error) {
    console.error("删除图片出错:", error);
    res.status(500).json({ message: "删除图片失败" });
  }
});

// 修改图片信息的路由 (使用POST请求)
app.post(
  "/images/update/:id",
  express.json(),
  async (req: Request, res: Response) => {
    const imageId = req.params.id;
    // 从 req.body 中获取 tags 字段，并且将其从 JSON 字符串解析为数组
    let tags = req.body.tags;

    if (!imageId) {
      return res.status(400).json({ message: "缺少图片 ID 参数" });
    }

    if (!tags) {
      return res.status(400).json({ message: "缺少 tags 参数" });
    }

    try {
      // 如果 tags 是字符串，尝试解析为数组
      if (typeof tags === "string") {
        tags = JSON.parse(tags);
      }

      // 验证解析后的 tags 是否为数组
      if (!Array.isArray(tags)) {
        return res
          .status(400)
          .json({ message: "标签格式不正确，应为数组或数组的 JSON 字符串" });
      }
    } catch (parseError) {
      console.error("解析 tags 字段出错:", parseError);
      return res.status(400).json({ message: "tags 字段解析失败" });
    }

    try {
      // 检查图片是否存在
      const queryCheck = "SELECT * FROM images WHERE id = ?";
      const [rows] = await pool.execute(queryCheck, [imageId]);

      if (!rows || rows.length === 0) {
        return res.status(404).json({ message: "未找到指定图片" });
      }

      // 更新图片信息
      const queryUpdate = "UPDATE images SET tags = ? WHERE id = ?";
      await pool.execute(queryUpdate, [JSON.stringify(tags), imageId]);

      res.status(200).json({ message: "图片信息更新成功", id: imageId });
    } catch (error) {
      console.error("更新图片信息出错:", error);
      res.status(500).json({ message: "更新图片信息失败" });
    }
  }
);

// 创建相册
app.post("/albums", express.json(), async (req: Request, res: Response) => {
  const { name, description, userId } = req.body;

  if (!name || !userId) {
    return res.status(400).json({ message: "缺少必要参数" });
  }

  try {
    // 将userId转换为整数（如果数据库中是整数类型）
    const parsedUserId = parseInt(userId, 10);

    // 检查相册名是否已存在
    const checkQuery = "SELECT * FROM albums WHERE name = ? AND user_id = ?";
    const [existingAlbums] = await pool.execute(checkQuery, [
      name,
      parsedUserId,
    ]);

    if (existingAlbums.length > 0) {
      console.log("相册名已存在:", name);
      return res.status(400).json({ message: "相册名已存在" });
    }

    // 创建新相册
    const query =
      "INSERT INTO albums (name, description, user_id) VALUES (?, ?, ?)";
    const [result] = await pool.execute(query, [
      name,
      description || "",
      parsedUserId,
    ]);

    console.log("相册创建成功:", result);

    // 获取新创建的相册信息
    const [newAlbumRows] = await pool.execute(
      "SELECT * FROM albums WHERE id = ?",
      [result.insertId]
    );

    // 检查结果是否存在
    if (newAlbumRows.length === 0) {
      console.log("无法获取新创建的相册信息");
      return res
        .status(500)
        .json({ message: "创建相册失败，无法获取相册信息" });
    }

    const newAlbum = newAlbumRows[0];

    res.status(201).json({
      // 使用201状态码表示创建成功
      message: "相册创建成功",
      id: newAlbum.id,
      name: newAlbum.name,
      description: newAlbum.description,
      userId: newAlbum.user_id,
      created_at: newAlbum.created_at,
      updated_at: newAlbum.updated_at,
    });
  } catch (error) {
    console.error("创建相册失败:", error);
    res.status(500).json({
      message: "创建相册失败",
      error: error instanceof Error ? error.message : "未知错误",
    });
  }
});

// 获取用户的所有相册
app.get("/albums", async (req: Request, res: Response) => {
  const userId = req.query.userId;

  if (!userId) {
    return res.status(400).json({ message: "缺少用户ID参数" });
  }

  try {
    const query =
      "SELECT * FROM albums WHERE user_id = ? ORDER BY created_at DESC";
    const [albums] = await pool.execute(query, [userId]);

    res.status(200).json(albums);
  } catch (error) {
    console.error("获取相册列表失败:", error);
    res.status(500).json({ message: "获取相册列表失败" });
  }
});

// 删除相册
app.delete("/albums/:id", async (req: Request, res: Response) => {
  const albumId = req.params.id;
  const userId = req.query.userId;

  if (!albumId || !userId) {
    return res.status(400).json({ message: "缺少必要参数" });
  }

  try {
    // 检查相册是否存在且属于该用户
    const checkQuery = "SELECT * FROM albums WHERE id = ? AND user_id = ?";
    const [albums] = await pool.execute(checkQuery, [albumId, userId]);

    if (albums.length === 0) {
      return res.status(404).json({ message: "相册不存在或无权删除" });
    }

    // 开始事务
    const connection = await pool.getConnection();
    await connection.beginTransaction();

    try {
      // 删除相册中的图片关联
      await connection.execute("DELETE FROM album_images WHERE album_id = ?", [
        albumId,
      ]);

      // 删除相册
      await connection.execute("DELETE FROM albums WHERE id = ?", [albumId]);

      // 提交事务
      await connection.commit();

      res.status(200).json({ message: "相册删除成功" });
    } catch (error) {
      // 回滚事务
      await connection.rollback();
      throw error;
    } finally {
      connection.release();
    }
  } catch (error) {
    console.error("删除相册失败:", error);
    res.status(500).json({ message: "删除相册失败" });
  }
});

// 更新相册信息
app.put("/albums/:id", express.json(), async (req: Request, res: Response) => {
  const albumId = req.params.id;
  const { name, description, userId } = req.body;

  if (!albumId || !name || !userId) {
    return res.status(400).json({ message: "缺少必要参数" });
  }

  try {
    // 检查相册是否存在且属于该用户
    const checkQuery = "SELECT * FROM albums WHERE id = ? AND user_id = ?";
    const [albums] = await pool.execute(checkQuery, [albumId, userId]);

    if (albums.length === 0) {
      return res.status(404).json({ message: "相册不存在或无权修改" });
    }

    // 检查新名称是否与其他相册重复
    const nameCheckQuery =
      "SELECT * FROM albums WHERE name = ? AND user_id = ? AND id != ?";
    const [existingAlbums] = await pool.execute(nameCheckQuery, [
      name,
      userId,
      albumId,
    ]);

    if (existingAlbums.length > 0) {
      return res.status(400).json({ message: "相册名已存在" });
    }

    // 更新相册信息
    const updateQuery =
      "UPDATE albums SET name = ?, description = ? WHERE id = ?";
    await pool.execute(updateQuery, [name, description || "", albumId]);

    res.status(200).json({
      message: "相册更新成功",
      albumId,
      name,
      description,
    });
  } catch (error) {
    console.error("更新相册失败:", error);
    res.status(500).json({ message: "更新相册失败" });
  }
});

// 启动服务器
app.listen(port, () => {
  console.log(`服务器运行在端口 ${port}`);
});
